#!usr/bin/env python3
#-*- coding:utf-8 -*-

#127.0.0.1:5000
#异步服务器

#Sublime Text选中一个单词,按两次ctrl+d即可编辑同一个变量


import logging;logging.basicConfig(level=logging.INFO);
import asyncio,os,json,time

from datetime import datetime
from aiohttp import web
from jinja2 import Environment,FileSystemLoader

import day3_orm

from day7_handlers import cookie2user,COOKIE_NAME

from day5_coroweb import add_routes,add_static
from day6_config import configs
orm = day3_orm

def init_jinja2(app,**kw):
	logging.info('init jinja2...')
	options = dict(
			autoescape = kw.get('autoescape',True),
			block_start_string = kw.get('block_start_string','{%'),
			block_end_string = kw.get('block_end_string','%}'),
			variable_start_string = kw.get('variable_start_string','{{'),
			variable_end_string = kw.get('variable_end_string','}}'),
			auto_reload = kw.get('auto_reload',True)

		)
	path = kw.get('path',None)
	if path is None:
		path = os.path.join(os.path.dirname(os.path.abspath(__file__)),'templates')
	logging.info('set jinja2 tempate path:%s' %path)
	env = Environment(loader=FileSystemLoader(path),**options)
	filters = kw.get('filters',None)
	if filters is not None:
		for name,f in filters.items():
			env.filters[name] = f

	app['__templating__'] = env 

async def logger_factory(app,handler):
	async def logger(request):
		logging.info('Request: %s %s' %(request.method,request.path))
		return (await handler(request))
	return logger
	
async def auth_factory(app,handler):
	async def auth(request):
		logging.info('check user:%s %s' % (request.method,request.path))
		request.__user__=None
		cookie_str = request.cookies.get(COOKIE_NAME)
		if cookie_str:
			user = await cookie2user(cookie_str)
			if user:
				logging.info('set current user:email=>%s,name=>%s'%(user.email,user.name))
				request.__user__ = user
		#未登陆跳到登陆界面,or not request.__user__.admin
		if request.path.startswith('/manage/') and (request.__user__ is None):
			return web.HTTPFound('/signin')
		print('auth_factory request.__user__=>',request.__user__)
		return (await handler(request))
	return auth
async def data_factory(app,handler):
	async def parse_data(request):
		if request.method == 'POST':
			content_type = request.content_type 
			if content_type.startswith('application/json'):
				request.__data__ = await request.json()
				logging.info('requset json : %s ' % str(request.__data__))
			elif content_type.startswith('application/x-www-from-urlencoded'):
				request.__data__ = await request.post()
				logging.info('requset from : %s ' % str(request.__data__))
		return (await handler(request))
	return parse_data;
	
async def response_factory(app,handler):
	async def response(request):
		logging.info('Response handler')
		r = await handler(request)
		logging.info('Response handler type(r)  => %s'%type(r))
		if isinstance(r,web.StreamResponse):
			return r
		if isinstance(r,bytes):
			resp = web.Response(body=r)
			resp.content_type='application/octet-stream'
			return resp
		if isinstance(r,str):
			if r.startswith('redirect:'):
				return web.HTTPFound(r[9:])
			resp = web.Response(body=r.encode('utf-8'))
			resp.content_type = 'text/html;charset=utf-8'
			return resp
		#解析返回dict的结果
		if isinstance(r,dict):
			template = r.get('__template__')
			if template is None: #没有模板的情况,当做json
				resp = web.Response(body=json.dumps(r,ensure_ascii=False,default=lambda obj: obj.__dict__).encode('utf-8'))
				resp.content_type = 'application/json;charset=utf-8'
			else:#解析模板
				r['__user__'] = request.__user__ #这里非常关键，把用户的数据绑定到结果
				resp = web.Response(body=app['__templating__'].get_template(template).render(**r).encode('utf-8'))
				resp.content_type = 'text/html;charset=utf-8'
			return resp
		minSec = 100
		maxSec = 600
		if isinstance(r,int) and r >=minSec and r < maxSec:
			return web.Response(r)
		if isinstance(r,tuple) and len(r) == 2:
			t,m = r
			if isinstance(t,int) and t >=minSec and t< maxSec:
				return web.Response(t,str(m))
		#default :
		resp = web.Response(body=str(r).encode('utf-8'))
		resp.content_type = 'text/plain;charset=utf-8'
		return resp
	return response

def datetime_filter(t):
	delta = int(time.time()-t)
	minSec = 60 #一分钟的秒数
	hourSec = 3600
	daySec = 86400
	yearSec = 604800
	if delta < minSec:
		return u'1分钟前'
	if delta < hourSec:
		return u'%s分钟前'%(delta//minSec)
	if  delta < daySec:#一天的秒数
		return u'%s小时前'%(delta//hourSec)
	if  delta<yearSec:
		return u'%s天前' %(delta//daySec)
	dt = datetime.fromtimestamp(t)
	return u'%s年%s月%s日'%(dt.year,dt.month,dt.day)

def index(request):
	return web.Response(body=b'<h1>awesome</h1>') #响应http请求


async def init(loop):
	ip = '127.0.0.1'
	port = 5000		
	await orm.create_pool(loop=loop,**configs.db) #
	factorys =[logger_factory,auth_factory,response_factory] 
	app = web.Application(loop=loop,middlewares=factorys)
	init_jinja2(app,filters=dict(datetime=datetime_filter)) #用于过滤模板中的时间日期格式
	add_routes(app,'day7_handlers')
	add_static(app)
	serv = await loop.create_server(app.make_handler(),ip,port)
	logging.info("server started at %s:%s"%(ip,str(port)))
	return serv

loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()

